﻿package little.bunny;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.webkit.URLUtil;

public class Updater{
	private static final String TAG = Updater.class.getName();
	//private static final String VER_JSON = "ver.json";
	private static final String APK_TYPE = "application/vnd.android.package-archive";

	private String host;
	private Context context;
	private ProgressDialog progressDialog;
	private Handler handler = new Handler();
	private String apkFullName = null;
	private double server_versionCode = 0;
	private String server_versionName;
	private String updateDir;
	private String VER_JSON;

	public Updater(String host, String verjson, Context context) {
		this(host, verjson, null, context);
	}

	public Updater(String host, String verjson, String savepath, Context context) {
		this.host = host;
		this.VER_JSON = verjson;
		this.context = context;
		this.updateDir = (savepath == null) ? Environment.getExternalStorageDirectory() + "/xbtupdate/" : Environment.getExternalStorageDirectory() + savepath;
	}
	
	/*
	public String getVesionName() {
		String versionName = null;
		try {
			versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
		} catch (NameNotFoundException e) {
			Log.e(TAG, e.getMessage());
		}

		return versionName;
	}
	*/
	
	public int getLocalVersionCode() {
		int l_versionCode = 0;
		try {
			l_versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
		} catch (NameNotFoundException e) {
			Log.e(TAG, e.getMessage());
		}

		return l_versionCode;
	}

	public double getRemoteVersionCode() {
		if (server_versionCode == 0) {
			try {
				getRemoteJSON();
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
			}
		}
		return this.server_versionCode;
	}
	
	/*
	public String getRemoteVersionName() {
		if (this.server_versionName == null) {
			try {
				getRemoteJSON();
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
			}
		}
		return this.server_versionName;
	}
	*/
	
	

	public boolean needUpdate() {
		double x1 = getRemoteVersionCode();
		if (x1 == -1)
		{
			return false;
		}
		else
		{
			return ( x1> getLocalVersionCode());
		}
	}
	
	
	public void showNewVersionUpdate() {
		if (this.server_versionName == null) {
			try {
				getRemoteJSON();
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
			}
		}
		
		String message = String.format("%s: %s, %s", context.getString(R.string.found_newversion), this.server_versionName, context.getString(R.string.need_update));
		AlertDialog dialog = new AlertDialog.Builder(context).setTitle(context.getString(R.string.alertdialog_title)).setMessage(message)
		// update
				.setPositiveButton(context.getString(R.string.alertdialog_update_button), new DialogInterface.OnClickListener() {
					
					public void onClick(DialogInterface dialog, int which) {
						progressDialog = new ProgressDialog(context);
						progressDialog.setTitle(context.getString(R.string.progressdialog_title));
						progressDialog.setMessage(context.getString(R.string.progressdialog_message));
						progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
						dialog.dismiss();
						download(getUpdateURL());
					}
					// cancel
				}).setNegativeButton(context.getString(R.string.alertdialog_cancel_button), new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						dialog.dismiss();
					}
				}).create();
		dialog.show();
	}
	
	
	private void getRemoteJSON() throws ClientProtocolException, IOException, JSONException {
		String url = host + VER_JSON;
		if (URLUtil.isHttpUrl(url)) {
			StringBuilder sb = new StringBuilder();
			HttpClient client = new DefaultHttpClient();
			HttpParams httpParams = client.getParams();
			HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
			HttpConnectionParams.setSoTimeout(httpParams, 5000);
			HttpResponse response = null;
			try
			{
				response= client.execute(new HttpGet(url));	
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"), 8192);

					String line = null;
					while ((line = reader.readLine()) != null) {
						sb.append(line + "\n");
					}
					reader.close();
				}
				else
				{
					this.server_versionCode = -1;
					return ;
				}
			}
			catch (Exception e) {
				Log.e(TAG, e.getMessage());
				this.server_versionCode = -1;
				return ;
			}
						

			try
			{
				JSONObject jsonObject = new JSONObject(sb.toString()).getJSONObject("update_ver"); 
				this.apkFullName = jsonObject.getString("fileName");
				this.server_versionName = jsonObject.getString("verName");
				this.server_versionCode = jsonObject.getDouble("verCode");
			}
			catch (Exception e) {
				Log.e(TAG, e.getMessage());
			}
		}
	}

	private String getUpdateURL() {
		return this.host + this.apkFullName;
	}

	private String getRemoteFileName() {
		if (this.apkFullName == null) {
			try {
				getRemoteJSON();
			} catch (Exception e) {
				Log.e(TAG, e.getMessage());
			}
		}

		return this.apkFullName;
	}
	
	private void download(final String url) {
		progressDialog.show();
		new Thread() {
			public void run() {
				HttpClient client = new DefaultHttpClient();
				HttpGet get = new HttpGet(url);
				HttpResponse response;
				try {
					response = client.execute(get);
					HttpEntity entity = response.getEntity();
					long length = entity.getContentLength();
					InputStream is = entity.getContent();
					FileOutputStream fileOutputStream = null;
					if (is != null) {
						File f = new File(updateDir);
						if (!f.exists()) {
							f.mkdirs();
						}
						fileOutputStream = new FileOutputStream(new File(updateDir, getRemoteFileName()));

						byte[] buf = new byte[1024];
						int ch = -1;
						int count = 0;
						while ((ch = is.read(buf)) != -1) {
							fileOutputStream.write(buf, 0, ch);
							count += ch;
							Log.d(TAG, String.valueOf(count));
							if (length > 0) {
							}
						}
					}
					fileOutputStream.flush();
					if (fileOutputStream != null) {
						fileOutputStream.close();
					}

					handler.post(new Runnable() {
						public void run() {
							progressDialog.cancel();
							installUpdate();
						}
					});
				} catch (Exception e) {
					progressDialog.cancel();
					Log.e(TAG, e.getMessage());
				}
			}

		}.start();
	}

	private void installUpdate() {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.fromFile(new File(updateDir, getRemoteFileName())), APK_TYPE);
		context.startActivity(intent);
	}
}
